/***********************************************************************
 * This file is a basic template for creating C code for a terminal    *
 * device.  Copy this file into your project directory and modify or   *
 * add to it as needed.                                                *  
 *                                                                     *
 * If interrupts are not used, all code presented for that interrupt   *
 * can be removed or commented out with C-style comment declarations.  *
 *                                                                     *
 * For additional information about dsPIC architecture and language    *
 * tools, refer to the following documents:                            *
 *                                                                     *
 * 16-Bit Language Tools Getting Started                  : DS51316    *
 * MPLAB C Compiler for                                                *
 *           PIC24 MCUs and dsPIC DSCs User's Guide       : DS51284    *
 * MPLAB Assembler, Linker and Utilities for                           *
 *           PIC24 MCUs and dsPIC DSCs User's Guide       : DS51317    *
 * 16-Bit Language Tools Libraries                        : DS51456    *
 *                                                                     *
 * For the latest Datasheets and Family Reference Guides, please       *
 * see the Microchip web site.                                         *
 *                                                                     *
 * Template file has been compiled with MPLAB C30 v3.20.               *
 *                                                                     *
 ***********************************************************************
 *                                                                     * 
 *    Author:                                                          *
 *    Company:                                                         * 
 *    Filename:       CommandProc.c                                       *
 *    Date:           3/8/2009                                         *
 *    File Version:   0.0.1                                            *
 *    Other Files Required: p24FJ16GA002.h, p24FJ16GA002.gld           *
 *    Tools Used: MPLAB IDE -> 8.10                                    *
 *                Compiler  -> 3.20                                    *
 *                                                                     *
 *    Devices Supported:                                               *
 *                p24FJ16GA002                                         *
 *                p24FJ16GA004                                         *
 ***********************************************************************
 *                                                                     *
 * Other Comments:                                                     *
 *                                                                     *
 * 1) C attributes, designated by the __attribute__ keyword, provide a *
 *    means to specify various characteristics of a variable or        *
 *    function, such as where a particular variable should be placed   *
 *    in memory, whether the variable should be aligned to a certain   *
 *    address boundary, whether a function is an Interrupt Service     *
 *    Routine (ISR), etc. If no special characteristics need to be     *
 *    specified for a variable or function, then attributes are not    *
 *    required. For more information about attributes, refer to the    *
 *    C30 User's Guide.                                                *
 *                                                                     *
 * 2) The space(xmemory) and space(ymemory) attributes are             *
 *    used to place a variable in X data space and Y data space,       *
 *    respectively. Variables accessed by dual-source DSP instructions *
 *    must be defined using these attributes.                          *
 *                                                                     *
 * 3) The aligned(k) attribute, used in variable definitions, is used  *
 *    to align a variable to the nearest higher 'k'-byte address       * 
 *    boundary. 'k' must be substituted with a suitable constant       *
 *    number when the ModBuf_X(k) or ModBuf_Y(k) macro is invoked.     *
 *    In most cases, variables are aligned either to avoid potential   *
 *    misaligned memory accesses, or to configure a modulo buffer.     *
 *                                                                     *
 * 4) The interrupt attribute is used to qualify a function as an      *
 *    interrupt service routine. An interrupt routine can be further   *
 *    configured to save certain variables on the stack, using the     *
 *    save(var-list) directive. If constants or string literals may    *
 *    be accessed using the default constants-in-code memory model,    *
 *    then the auto_psv attribute is included. If no constants or      *
 *    string literals will be accessed, the no_auto_psv attribute      *
 *    can be included, saving a few cycles of latency.                 *
 *                                                                     *
 * 5) The shadow attribute is used to set up any function to           *
 *    perform a fast context save using shadow registers.              *
 *                                                                     *
 * 6) Note the use of double-underscores (__) at the start and end of  *
 *    the attribute keyword mentioned above.                           *
 *                                                                     *
 **********************************************************************/
#include "GenericTypeDefs.h"
#include "CommandProc.h"
#include "Terminal.h"
#ifdef __DEBUG
#include <stdio.h>
static char *IndName[]={"InitInd","PositionInd","NormalInd","AbnormalInd","ErrorInd"};
static char *ReqName[]={"InitReq","PositionReq","NormalReq","AbnormalReq","ErrorReq"};
#endif
extern T_terminal Terminal;

/****************************************************************************
Function Prototype : UINT8	Indicator_process ( T_ReqIndbuf commbuf )

Include            : CommandProc.h
 
Description      : This function process the data received
 
Arguments       : commbuf -- data buffer received
					 
Return Value    : 1-OK; 0-ERR
 
Remarks           : 
 ******************************************************************************/
UINT8 Indicator_process(T_ReqIndbuf commbuf)
{
    switch (commbuf.AFN)
    {
        case AFN_NORMAL:
        {
            if ((commbuf.SEQ == SEQ_IND)
                    && (commbuf.Length == PAYLOAD_LENGTH)
                    && (commbuf.payload.NormalInd.DA1 == IND_SLOT_DA)
                    && (commbuf.payload.NormalInd.DA2 == IND_TIME_DA))
            {
                Terminal.runtimePara.Terminal_Slot = commbuf.payload.NormalInd.Terminal_Slot;
                Terminal.runtimePara.Terminal_Time = commbuf.payload.NormalInd.Terminal_Time;
#ifdef __DEBUG
                printf("decode Indictor: %s successful\n",IndName[2]);
#endif
            }
            else
            {
#ifdef __DEBUG
                printf("decode Indictor: %s fail\n",IndName[2]);
#endif
                return ( FALSE);
            }
        }
            break;
        case AFN_ABNORMAL:
        {
            if ((commbuf.SEQ == SEQ_IND)
                    && (commbuf.Length == PAYLOAD_LENGTH)
                    && (commbuf.payload.AbnormalInd.DA1 == IND_SLOT_DA)
                    && (commbuf.payload.AbnormalInd.DA2 == IND_TIME_DA))
            {
                Terminal.runtimePara.Terminal_Slot = commbuf.payload.AbnormalInd.Terminal_Slot;
                Terminal.runtimePara.Terminal_Time = commbuf.payload.AbnormalInd.Terminal_Time;
                if (Terminal.runtimePara.currentState == terminalStateAbnormal)
                {
                    Terminal.runtimePara.lastState = Terminal.runtimePara.currentState;
                    Terminal.runtimePara.currentState = terminalStateNormal;
                }
#ifdef __DEBUG
                printf("decode Indictor: %s successful\n",IndName[3]);
#endif
            }
            else
            {
#ifdef __DEBUG
                printf("decode Indictor: %s fail\n",IndName[3]);
#endif
                return ( FALSE);
            }
        }
            break;
        case AFN_POSITION:
        {
            if ((commbuf.SEQ == SEQ_IND)
                    && (commbuf.Length == PAYLOAD_LENGTH)
                    && (commbuf.payload.PositionInd.DA1 == IND_CHANNEL_DA)
                    && (commbuf.payload.PositionInd.DA2 == IND_POWER_DA)
                    && (commbuf.payload.PositionInd.DA3 == IND_SLOT_DA)
                    && (commbuf.payload.PositionInd.DA4 == IND_TIME_DA))
            {
                Terminal.runtimePara.Node_ID = commbuf.SA;
                Terminal.runtimePara.Terminal_Channel = commbuf.payload.PositionInd.Terminal_Channel;
                Terminal.runtimePara.Terminal_Power = commbuf.payload.PositionInd.Terminal_Power;
                Terminal.runtimePara.Terminal_Slot = commbuf.payload.PositionInd.Terminal_Slot;
                Terminal.runtimePara.Terminal_Time = commbuf.payload.PositionInd.Terminal_Time;
                if (Terminal.runtimePara.currentState == terminalStateIdle)
                {
                    Terminal.runtimePara.lastState = Terminal.runtimePara.currentState;
                    Terminal.runtimePara.currentState = terminalStateNormal;
                }
#ifdef __DEBUG
                printf("decode Indictor: %s successful\n",IndName[1]);
#endif
            }
            else
            {
#ifdef __DEBUG
                printf("decode Indictor: %s fail\n",IndName[1]);
#endif
                return ( FALSE);
            }
        }
            break;
        case AFN_INIT:
        {
            if ((commbuf.SEQ == SEQ_IND)
                    && (commbuf.Length == PAYLOAD_LENGTH)
                    && (commbuf.payload.InitInd.DA1 == IND_TID_DA))
            {
                Terminal.runtimePara.Terminal_ID = commbuf.payload.InitInd.Terminal_ID;
#ifdef __DEBUG
                printf("decode Indictor: %s successful\n",IndName[0]);
#endif
            }
            else
            {
#ifdef __DEBUG
                printf("decode Indictor: %s fail\n",IndName[0]);
#endif
                return ( FALSE);
            }
        }
            break;
        default:
        {
#ifdef __DEBUG
                printf("decode Indictor: %s fail\n",IndName[5]);
#endif
            return ( FALSE);
        }
            break;
    }
    return ( TRUE);
}

/****************************************************************************
Function Prototype : UINT8	Request_Creat ( UINT8 state )

Include            : CommandProc.h
 
Description      : This function process the data sent
 
Arguments       : UINT8 state -- state of state machine 
					 
Return Value    : T_ReqIndbuf -- data buffer sent
 
Remarks           : 
 ******************************************************************************/
UINT8 Request_Creat(UINT8 state)
{
    T_ReqIndbuf *buf = &Terminal.Reqbuf;

    switch (state)
    {
        case terminalStateIdle:
        {
            if (Terminal.runtimePara.Terminal_ID != 0) //in config mode
            {
                buf->SA = Terminal.runtimePara.Terminal_ID;
                buf->Length = PAYLOAD_LENGTH;
                buf->AFN = AFN_POSITION;
                buf->SEQ = SEQ_REQ;
                buf->payload.PositionReq.DA1 = REQ_STATUS_DA;
                buf->payload.PositionReq.Terminal_Status = Terminal.runtimePara.Terminal_Status;
#ifdef __DEBUG
                printf("creat Request: %s successful\n",ReqName[1]);
#endif
            }
            else //in init mode
            {
                buf->SA = Terminal.SerialNo;
                buf->Length = PAYLOAD_LENGTH;
                buf->AFN = AFN_INIT;
                buf->SEQ = SEQ_REQ;
#ifdef __DEBUG
                printf("creat Request: %s successful\n",ReqName[0]);
#endif
            }
        }
            break;
        case terminalStateNormal:
        {
            buf->SA = Terminal.runtimePara.Terminal_ID;
            buf->Length = PAYLOAD_LENGTH;
            buf->AFN = AFN_NORMAL;
            buf->SEQ = SEQ_REQ;
            buf->payload.PositionReq.DA1 = REQ_STATUS_DA;
            buf->payload.PositionReq.Terminal_Status = Terminal.runtimePara.Terminal_Status;
#ifdef __DEBUG
                printf("creat Request: %s successful\n",ReqName[2]);
#endif
        }
            break;
        case terminalStateAbnormal:
        {
            buf->SA = Terminal.runtimePara.Terminal_ID;
            buf->Length = PAYLOAD_LENGTH;
            buf->AFN = AFN_ABNORMAL;
            buf->SEQ = SEQ_REQ;
            buf->payload.PositionReq.DA1 = REQ_STATUS_DA;
            buf->payload.PositionReq.Terminal_Status = Terminal.runtimePara.Terminal_Status;
#ifdef __DEBUG
                printf("creat Request: %s successful\n",ReqName[3]);
#endif
        }
            break;
        default:
        {
#ifdef __DEBUG
             printf("creat Request: %s fail\n",ReqName[5]);
#endif
            return ( FALSE);
        }
    }
    return ( TRUE);
}

#ifdef __DEBUG
/****************************************************************************
Function Prototype  : T_ReqIndbuf	Indicator_Creat ( UINT8 state )

Include             : CommandProc.h

Description         : This function creat the data sent from NODE

Arguments           : UINT8 sort -- sort of Indictor

Return Value        : UINT8 -- data buffer sent OK/FAIL

Remarks             : only used in debug mode
 ******************************************************************************/
BOOL Indicator_Creat( UINT8 sort )
{
    T_ReqIndbuf *buf = &Terminal.Indbuf;
    printf("creat Ind: %s\n",IndName[sort]);
    buf->SA = 0x12345678;
    buf->Length = PAYLOAD_LENGTH;
    switch ( sort )
    {
        case 0:
        {
            buf->AFN = AFN_INIT;
            buf->SEQ = SEQ_IND;
            buf->payload.InitInd.DA1 = IND_TID_DA;
            buf->payload.InitInd.Terminal_ID = 0xBEEFBEEF;
        }
            break;
        case 1:
        {
            buf->AFN = AFN_POSITION;
            buf->SEQ = SEQ_IND;
            buf->payload.PositionInd.DA1 = IND_CHANNEL_DA;
            buf->payload.PositionInd.Terminal_Channel = 1;
            buf->payload.PositionInd.DA2 = IND_POWER_DA;
            buf->payload.PositionInd.Terminal_Power = 2;
            buf->payload.PositionInd.DA3 = IND_SLOT_DA;
            buf->payload.PositionInd.Terminal_Slot = 3;
            buf->payload.PositionInd.DA4 = IND_TIME_DA;
            buf->payload.PositionInd.Terminal_Time = 4;
        }
            break;
        case 2:
        {
            buf->AFN = AFN_NORMAL;
            buf->SEQ = SEQ_IND;
            buf->payload.NormalInd.DA1 = IND_SLOT_DA;
            buf->payload.NormalInd.Terminal_Slot = 3;
            buf->payload.NormalInd.DA2 = IND_TIME_DA;
            buf->payload.NormalInd.Terminal_Time = 4;
        }
            break;
        case 3:
        {
            buf->AFN = AFN_ABNORMAL;
            buf->SEQ = SEQ_IND;
            buf->payload.AbnormalInd.DA1 = IND_SLOT_DA;
            buf->payload.AbnormalInd.Terminal_Slot = 1;
            buf->payload.AbnormalInd.DA2 = IND_TIME_DA;
            buf->payload.AbnormalInd.Terminal_Time = 2;
        }
            break;
        default:
        {
            return ( FALSE );
        }
    }
    return ( TRUE);
}

/****************************************************************************
Function Prototype : UINT8 Request_process(T_ReqIndbuf commbuf)

Include            : CommandProc.h

Description      : This function process the data received by node

Arguments       : commbuf -- data buffer received

Return Value    : 1-OK; 0-ERR

Remarks           :
 ******************************************************************************/
UINT8 Request_process(T_ReqIndbuf commbuf)
{
    switch (commbuf.AFN)
    {
        case AFN_POSITION:
        case AFN_NORMAL:
        case AFN_ABNORMAL:
        {
            if ((commbuf.SEQ == SEQ_REQ)
                    && (commbuf.Length == PAYLOAD_LENGTH)
                    && (commbuf.payload.PositionReq.DA1 == REQ_STATUS_DA))
            {
                //TODO: add saving terminal status code here
                //XXX = commbuf.payload.PositionReq.Terminal_Status;
 
#ifdef __DEBUG
                printf("decode Request: p/n/ab successful\n");
#endif
            }
            else
            {
#ifdef __DEBUG
                printf("decode Request: p/n/ab fail\n");
#endif
                return ( FALSE);
            }
        }
            break;
        case AFN_INIT:
        {
            if ((commbuf.SEQ == SEQ_REQ)
                    && (commbuf.Length == PAYLOAD_LENGTH))
            {
                //TODO: add saving terminal serial_no code here
#ifdef __DEBUG
                printf("decode Request: Init Req successful\n");
#endif
            }
            else
            {
#ifdef __DEBUG
                printf("decode Request: Init fail\n");
#endif
                return ( FALSE);
            }
        }
            break;
        default:
        {
#ifdef __DEBUG
            printf("decode Request: %s fail\n",ReqName[5]);
#endif
            return ( FALSE);
        }
            break;
    }
    return ( TRUE);
}

#endif
